#pragma once
#include "Utils.h"
#include <string>
#include "BaseObjectWrapper.h"
namespace Smo
{
	using namespace std;
	class String : public BaseObjectWrapper<wstring>
	{
	public:
		virtual wstring ToString() const override
		{
			return mValue;
		}

		String(const wchar_t* str)
			: BaseObjectWrapper(wstring(str))
		{
		}

		String(const wstring& str)
			: BaseObjectWrapper(str)
		{
		}

		String(const char* str)
			: BaseObjectWrapper(Convert::ToString(str))
		{
		}

		String(const string& str)
			: BaseObjectWrapper(Convert::ToString(str))
		{
		}

		String& operator=(const wstring str)
		{
			this->mValue = str;
			return *this;
		}

		String& operator=(const wchar_t* str)
		{
			this->mValue = str;
			return *this;
		}

		String& operator=(const string& str)
		{
			this->mValue = Convert::ToString(str);
			return *this;
		}

		String& operator=(const char* str)
		{
			this->mValue = Convert::ToString(str);
		}

		String& operator+=(const String& str)
		{
			this->mValue.append(str.mValue);
			return *this;
		}

		String& operator+=(const wstring& str)
		{
			this->mValue.append(str);
			return *this;
		}

		String& operator+=(const wchar_t* str)
		{
			this->mValue.append(str);
			return *this;
		}

		String& operator+=(const string& str)
		{
			this->mValue.append(Convert::ToString(str));
			return *this;
		}

		String& operator+=(const char* str)
		{
			this->mValue.append(Convert::ToString(str));
			return *this;
		}

		String operator+(const String& right)
		{
			wstring s(mValue);
			s.append(right.mValue);
			return s;
		}

		String operator+(const wstring& right)
		{
			wstring s(mValue);
			s.append(right);
			return s;
		}

		String operator+(const wchar_t* right)
		{
			wstring s(mValue);
			s.append(right);
			return s;
		}

		String operator+(const string& right)
		{
			wstring s(mValue);
			s.append(Convert::ToString(right));
			return s;
		}

		String operator+(const char* right)
		{
			wstring s(mValue);
			s.append(Convert::ToString(right));
			return s;
		}

		virtual void Write(wostream& stream) const
		{
			stream << this->mValue;
		}
	};
}

using namespace Smo;
using namespace std;
String operator+(const char* left, const String& right)
{
	String s = left;
	s += right;
	return s;
}

String operator+(const wchar_t* left, const String& right)
{
	String s = left;
	s += right;
	return s;
}

wostream& operator<<(wostream& stream, const String& str)
{
	stream << str.GetValue();
	return stream;
}